import './index.less';
import { defineComponent, ref, computed, watch, onUnmounted, nextTick, onBeforeMount, onMounted } from 'vue';
import PropTypes from 'ant-design-vue/es/_util/vue-types';
import { debounce, isEmpty, isFunction } from 'lodash-es';
import ResizeListener from 'element-resize-detector';
import * as echarts from 'echarts';
import { Empty, Spin } from 'ant-design-vue';
export default defineComponent({
	name: 'BaseChart',
	props: {
		options: PropTypes.object.def(() => {}),
		loading: PropTypes.bool.def(false),
		image: PropTypes.any,
		description: PropTypes.any,
		mixinFunc: PropTypes.func,
		imageStyle: PropTypes.object,
		events: PropTypes.object.def(() => {}),
	},
	setup(props, { emit, expose }) {
		const cachedOptions = ref({});
		let chart = undefined;
		const chartRef = ref(undefined);
		const handleWindowResize = ref(() => {
			if (!chart) return;
			chart?.resize();
		});
		onBeforeMount(() => {
			handleWindowResize.value = debounce(handleWindowResize.value, 300);
		});
		const chartOptions = computed(() => {
			return {
				mixinFunc: props.mixinFunc,
				options: props.options,
			};
		});

		const stopHandler = watch(
			() => chartOptions.value,
			(val) => {
				const { mixinFunc, options } = val;
				if (!isEmpty(options)) {
					cachedOptions.value = isFunction(mixinFunc) ? mixinFunc(options) : options;
					// eslint-disable-next-line vue/valid-next-tick
					nextTick(() => {
						if (chart) {
							chart.clear();
						}
						renderChartView();
					}).then((r) => {});
				}
			},
			{
				immediate: true,
				deep: true,
			}
		);

		onMounted(() => {
			window.addEventListener('resize', handleWindowResize.value);
			addChartResizeListener();
		});

		const addChartResizeListener = () => {
			const instance = ResizeListener({
				strategy: 'scroll',
				callOnAdd: true,
			});
			instance?.listenTo(chartRef.value, () => {
				if (!chart) {
					return false;
				}
				chart.resize({
					animation: {
						duration: 500,
					},
				});
			});
		};

		const renderChartView = () => {
			chart = echarts.init(chartRef.value);
			chart.setOption(cachedOptions.value);
			chart.on('finished', () => {
				emit('load', chart, echarts);
			});
			if (!isEmpty(props.events)) {
				Object.keys(props.events).map((e) => {
					chart.off(e);
					chart.on(e, props.events[e]);
				});
			}
		};

		onUnmounted(() => {
			stopHandler();
			window.removeEventListener('resize', handleWindowResize.value);
			if (chart) {
				chart.dispose();
				chart = null;
			}
		});

		return () => {
			return (
				<div class="base-chart">
					{isEmpty(props.options) ? (
						<div class="base-chart-empty">
							<Empty />
						</div>
					) : null}
					{props.loading ? (
						<div class="base-chart-loading">
							<Spin spinning={props.loading} />
						</div>
					) : null}
					<div class="base-chart-core" ref={chartRef} />
				</div>
			);
		};
	},
});
